package com.datagateway.component;

import com.datagateway.model.ProcessedData;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.InsertManyOptions;
import com.mongodb.client.result.InsertManyResult;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * MongoDB数据源实现
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
public class MongoDBDataSource implements DataSourceManager.DataSourceInstance {

    private static final Logger logger = LoggerFactory.getLogger(MongoDBDataSource.class);

    private final Map<String, Object> config;
    private final String type = "MONGODB";
    private MongoClient mongoClient;
    private MongoDatabase database;
    private MongoCollection<Document> collection;
    private boolean connected = false;

    public MongoDBDataSource(Map<String, Object> config) {
        this.config = new ConcurrentHashMap<>(config);
        initialize();
    }

    /**
     * 初始化MongoDB连接
     */
    private void initialize() {
        try {
            String connectionString = (String) config.get("connectionString");
            String databaseName = (String) config.getOrDefault("database", "datagateway");
            String collectionName = (String) config.getOrDefault("collection", "processed_data");

            // 建立连接
            mongoClient = MongoClients.create(connectionString);
            database = mongoClient.getDatabase(databaseName);
            collection = database.getCollection(collectionName);
            connected = true;

            logger.info("MongoDB数据源初始化成功: database={}, collection={}", databaseName, collectionName);

        } catch (Exception e) {
            logger.error("MongoDB数据源初始化失败: {}", e.getMessage(), e);
            connected = false;
        }
    }

    @Override
    public boolean testConnection() {
        try {
            if (mongoClient == null) {
                initialize();
            }

            if (mongoClient != null) {
                // 执行ping操作测试连接
                database.runCommand(new Document("ping", 1));
                connected = true;
                return true;
            }
            return false;

        } catch (Exception e) {
            logger.error("MongoDB连接测试失败: {}", e.getMessage(), e);
            connected = false;
            return false;
        }
    }

    @Override
    public boolean writeData(List<ProcessedData> dataList) {
        if (!connected || collection == null) {
            logger.error("MongoDB连接未建立");
            return false;
        }

        if (dataList == null || dataList.isEmpty()) {
            return true;
        }

        try {
            List<Document> documents = new ArrayList<>();
            for (ProcessedData data : dataList) {
                Document document = convertProcessedDataToDocument(data);
                documents.add(document);
            }

            // 批量插入
            InsertManyOptions options = new InsertManyOptions().ordered(false);
            InsertManyResult result = collection.insertMany(documents, options);

            logger.info("MongoDB数据写入成功: count={}, inserted={}", 
                dataList.size(), result.getInsertedIds().size());
            return true;

        } catch (Exception e) {
            logger.error("MongoDB数据写入失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public List<ProcessedData> readData(String query, Map<String, Object> parameters) {
        if (!connected || collection == null) {
            logger.error("MongoDB连接未建立");
            return Collections.emptyList();
        }

        List<ProcessedData> resultList = new ArrayList<>();

        try {
            // 解析查询条件
            Bson filter = parseQueryToBson(query, parameters);

            // 执行查询
            for (Document document : collection.find(filter)) {
                ProcessedData data = convertDocumentToProcessedData(document);
                resultList.add(data);
            }

            logger.info("MongoDB数据读取成功: count={}", resultList.size());
            return resultList;

        } catch (Exception e) {
            logger.error("MongoDB数据读取失败: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }

    @Override
    public boolean executeSql(String sql, Map<String, Object> parameters) {
        if (!connected || database == null) {
            logger.error("MongoDB连接未建立");
            return false;
        }

        try {
            // MongoDB不支持SQL，这里可以执行一些管理命令
            if (sql.toLowerCase().startsWith("create collection")) {
                String collectionName = extractCollectionName(sql);
                database.createCollection(collectionName);
                logger.info("MongoDB集合创建成功: {}", collectionName);
                return true;
            } else if (sql.toLowerCase().startsWith("drop collection")) {
                String collectionName = extractCollectionName(sql);
                database.getCollection(collectionName).drop();
                logger.info("MongoDB集合删除成功: {}", collectionName);
                return true;
            } else {
                logger.warn("MongoDB不支持SQL语句: {}", sql);
                return false;
            }

        } catch (Exception e) {
            logger.error("MongoDB命令执行失败: sql={}, error={}", sql, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean isConnected() {
        try {
            if (mongoClient == null) {
                return false;
            }
            // 执行ping操作检查连接
            database.runCommand(new Document("ping", 1));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void close() {
        try {
            if (mongoClient != null) {
                mongoClient.close();
            }
            connected = false;
            logger.info("MongoDB数据源连接已关闭");
        } catch (Exception e) {
            logger.error("关闭MongoDB连接失败: {}", e.getMessage(), e);
        }
    }

    @Override
    public String getType() {
        return type;
    }

    @Override
    public Map<String, Object> getConfig() {
        return new HashMap<>(config);
    }

    /**
     * 将ProcessedData转换为MongoDB Document
     */
    private Document convertProcessedDataToDocument(ProcessedData data) {
        Document document = new Document();
        document.append("_id", data.getId());
        document.append("id", data.getId());
        document.append("content", data.getContent());
        document.append("timestamp", data.getTimestamp());
        document.append("created_time", new Date());
        
        // 添加metadata
        if (data.getMetadata() != null && !data.getMetadata().isEmpty()) {
            Document metadataDoc = new Document();
            for (Map.Entry<String, Object> entry : data.getMetadata().entrySet()) {
                metadataDoc.append(entry.getKey(), entry.getValue());
            }
            document.append("metadata", metadataDoc);
        }
        
        return document;
    }

    /**
     * 将MongoDB Document转换为ProcessedData
     */
    private ProcessedData convertDocumentToProcessedData(Document document) {
        ProcessedData data = new ProcessedData();
        data.setId(document.getString("id"));
        data.setContent(document.getString("content"));
        data.setTimestamp(document.getLong("timestamp"));
        
        // 解析metadata
        Document metadataDoc = document.get("metadata", Document.class);
        if (metadataDoc != null) {
            Map<String, Object> metadata = new HashMap<>();
            for (Map.Entry<String, Object> entry : metadataDoc.entrySet()) {
                metadata.put(entry.getKey(), entry.getValue());
            }
            data.setMetadata(metadata);
        }
        
        return data;
    }

    /**
     * 解析查询条件为Bson
     */
    private Bson parseQueryToBson(String query, Map<String, Object> parameters) {
        // 简单的查询解析，实际项目中可以使用更复杂的解析器
        if (query == null || query.trim().isEmpty()) {
            return new Document(); // 空查询，返回所有文档
        }

        try {
            // 支持简单的等值查询
            if (query.contains("=")) {
                String[] conditions = query.split(" AND ");
                List<Bson> filters = new ArrayList<>();
                
                for (String condition : conditions) {
                    String[] parts = condition.split("=");
                    if (parts.length == 2) {
                        String field = parts[0].trim();
                        String value = parts[1].trim();
                        
                        // 处理参数替换
                        if (value.startsWith(":")) {
                            String paramName = value.substring(1);
                            Object paramValue = parameters.get(paramName);
                            if (paramValue != null) {
                                filters.add(Filters.eq(field, paramValue));
                            }
                        } else {
                            // 直接值
                            filters.add(Filters.eq(field, value));
                        }
                    }
                }
                
                if (filters.size() == 1) {
                    return filters.get(0);
                } else if (filters.size() > 1) {
                    return Filters.and(filters);
                }
            }
            
            // 默认返回空查询
            return new Document();
            
        } catch (Exception e) {
            logger.error("解析MongoDB查询失败: query={}, error={}", query, e.getMessage(), e);
            return new Document();
        }
    }

    /**
     * 从SQL语句中提取集合名称
     */
    private String extractCollectionName(String sql) {
        try {
            String[] parts = sql.split("\\s+");
            for (int i = 0; i < parts.length - 1; i++) {
                if ("collection".equalsIgnoreCase(parts[i])) {
                    return parts[i + 1];
                }
            }
            return "processed_data"; // 默认集合名
        } catch (Exception e) {
            logger.error("提取集合名称失败: sql={}, error={}", sql, e.getMessage(), e);
            return "processed_data";
        }
    }
}
